#include "PlayerEvent.h"
#include "Log.h"
#include "ChestLock.h"

#include "GameSingleton.h"
#include "GameRegistry.hpp"

#include "Expand/Plugins/AuthPlugin.h"

#include "Blocks/ChestBlock.h"
#include "Player/PlayerData.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentBlockEntity.h"
#include "Components/ComponentMiner.h"

#include "Network/PackageManager.h"
#include "Network/Packages/MessagePackage.h"

#include "Subsystems/SubsystemTerrain.h"
#include "Subsystems/SubsystemPlayers.h"

namespace CXHGT
{

    PlayerEvent::PlayerEvent(ChestLock * chestLock) : m_chestLock(chestLock)
    {
        m_subsystemTerrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();
        m_subsystemPlayers = GameSingleton::singletonPtr->getSingleton<SubsystemPlayers>();
    }

    static void sendMessage(ClientPtr client, const std::string & message)
    {
        std::shared_ptr<MessagePackage> package = std::make_shared<MessagePackage>(message);
        package->client = client;
        package->sendType = PackageSendType::TARGET;
        GameSingleton::packageManager->addSendPackageToQueue(package);
    }

    bool PlayerEvent::playerPlaceBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t placeBlockValue)
    {
        if (m_subsystemTerrain->getCellContents(point) == ChestBlock::Index() && m_chestLock->authPlugin->getLevelByGuid(componentPlayer->playerData->playerGuid) < 100)
        {
            GameGuid ownerGuid;
            if (m_chestLock->getOwner(point, ownerGuid) && ownerGuid != componentPlayer->playerData->playerGuid)
            {
                std::string playerName;
                if (m_subsystemPlayers->playerGuidGetName(ownerGuid,playerName))
                {
                    sendMessage(componentPlayer->playerData->client, fmt::format("走开，这是 {} 的箱子，不是你的", playerName));
                }
                else
                {
                    sendMessage(componentPlayer->playerData->client, "该箱子已经上锁了，无法在该位置放置其它方块");
                }
                return false;
            }
        }
        return true;
    }

    bool PlayerEvent::playerBreakBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t digBlockValue, int32_t toolLevel)
    {
        if (m_subsystemTerrain->getCellContents(point) == ChestBlock::Index())
        {
            GameGuid ownerGuid;
            if (m_chestLock->getOwner(point, ownerGuid))
            {
                if ((ownerGuid == componentPlayer->playerData->playerGuid || m_chestLock->authPlugin->getLevelByGuid(componentPlayer->playerData->playerGuid) >= 100))
                {
                    m_chestLock->breakChest(point);
                }
                else
                {
                    std::string playerName;
                    if (m_subsystemPlayers->playerGuidGetName(ownerGuid,playerName))
                    {
                        sendMessage(componentPlayer->playerData->client, fmt::format("走开，这是 {} 的箱子，不是你的", playerName));
                    }
                    else
                    {
                        sendMessage(componentPlayer->playerData->client, "该箱子已经上锁了，无法破坏");
                    }
                    return false;
                }
            }
        }
        return true;
    }

    bool PlayerEvent::openPointInventory(std::shared_ptr<PlayerData> playerData, const Point3 &point, IInventory *inventory)
    {
        if (inventory->blockEntity != nullptr)
        {
            GameGuid ownerGuid;
            if (m_chestLock->getOwner(point, ownerGuid))
            {
                if (m_chestLock->authPlugin->getLevelByGuid(playerData->playerGuid) < 100)
                {
                    std::string playerName;
                    if (m_subsystemPlayers->playerGuidGetName(ownerGuid,playerName))
                    {
                        sendMessage(playerData->client, fmt::format("走开，这是 {} 的箱子，不是你的", playerName));
                    }
                    else
                    {
                        sendMessage(playerData->client, "该箱子已经上锁了，无法破坏");
                    }
                    return false;
                }
            }
            else
            {
                IInventory *playerInventory = playerData->componentPlayer->componentMiner->inventory;
                int32_t slotValue = playerInventory->getSlotValue(playerInventory->getActiveSlotIndex());
                if (slotValue == m_chestLock->lockBlockValue)
                {
                    uint32_t num = playerInventory->removeSlotItems(playerInventory->getActiveSlotIndex(), 1);
                    if (num != 0)
                    {
                        if (m_chestLock->addChestLock(point, playerData->playerGuid))
                        {
                            sendMessage(playerData->client, "成功上锁箱子");
                        }
                        else
                        {
                            sendMessage(playerData->client, "上锁箱子失败");
                        }
                    }
                }
            }
        }
        return true;
    }

    bool PlayerEvent::playerHandleMoveItem(std::shared_ptr<PlayerData> playerData, IInventory *sourceInventory, uint32_t sourceSlotIndex, IInventory *targetInventory, int32_t targetSlotIndex, uint32_t count)
    {
        if (sourceInventory->blockEntity != nullptr)
        {
            const Point3& point = sourceInventory->blockEntity->coordinates;
            GameGuid ownerGuid;
            if (m_chestLock->getOwner(point, ownerGuid))
            {
                if (m_chestLock->authPlugin->getLevelByGuid(playerData->playerGuid) < 100)
                {
                    std::string playerName;
                    if (m_subsystemPlayers->playerGuidGetName(ownerGuid,playerName))
                    {
                        sendMessage(playerData->client, fmt::format("走开，这是 {} 的箱子，不是你的", playerName));
                    }
                    else
                    {
                        sendMessage(playerData->client, "该箱子已经上锁了，无法破坏");
                    }
                    return false;
                }
            }
        }
        return true;
    }

    bool PlayerEvent::playerHandleDragDrop(std::shared_ptr<PlayerData> playerData, IInventory *sourceInventory, uint32_t sourceSlotIndex, DragMode dragMode, IInventory *targetInventory, uint32_t targetSlotIndex, bool processingOnly)
    {
        if (sourceInventory->blockEntity != nullptr)
        {
            const Point3& point = sourceInventory->blockEntity->coordinates;
            GameGuid ownerGuid;
            if (m_chestLock->getOwner(point, ownerGuid))
            {
                if (m_chestLock->authPlugin->getLevelByGuid(playerData->playerGuid) < 100)
                {
                    std::string playerName;
                    if (m_subsystemPlayers->playerGuidGetName(ownerGuid,playerName))
                    {
                        sendMessage(playerData->client, fmt::format("走开，这是 {} 的箱子，不是你的", playerName));
                    }
                    else
                    {
                        sendMessage(playerData->client, "该箱子已经上锁了，无法破坏");
                    }
                    return false;
                }
            }
        }
        return true;
    }

    bool PlayerEvent::playerDrapDrop(ComponentPlayer *componentPlayer, const Vector3 &dropVelocity, IInventory *inventory, uint32_t slotIndex, uint32_t count)
    {
        if (inventory->blockEntity != nullptr)
        {
            const Point3& point = inventory->blockEntity->coordinates;
            GameGuid ownerGuid;
            PlayerDataPtr &playerData = componentPlayer->playerData;

            if (m_chestLock->getOwner(point, ownerGuid))
            {
                if (m_chestLock->authPlugin->getLevelByGuid(playerData->playerGuid) < 100)
                {
                    std::string playerName;
                    if (m_subsystemPlayers->playerGuidGetName(ownerGuid,playerName))
                    {
                        sendMessage(playerData->client, fmt::format("走开，这是 {} 的箱子，不是你的", playerName));
                    }
                    else
                    {
                        sendMessage(playerData->client, "该箱子已经上锁了，无法破坏");
                    }
                    return false;
                }
            }
        }
        return true;
    }

} // namespace BedWars
